package net.windward.RoboRally;

import net.windward.RoboRally.api.*;
import java.util.ArrayList;

import java.util.List;

public class Pathfinder extends AStar<Utilities.MovePoint>{

    int FATAL_DAMAGE = 10;

    Info info;
    GameMap map;
    Utilities.MovePoint goal;
    
    
    /* cost of path so far from a to b
    *
    * Just Manhattan distance for now
    * */
    protected Double g(Utilities.MovePoint a, Utilities.MovePoint b) {
        return (Utilities.manhattan_distance(a,b)
                + Utilities.calculateRisk(info, map, b.getLocation())
                + Utilities.CalcLaserDamage(map, b.getLocation())
                + (b.getDead() ? (Double)9001.0 : (Double)0.0)
                + ((b.getDamage() == FATAL_DAMAGE) ? (Double)9001.0 : (Double)0.0));
    }

    /* movement heuristic to get from a to b
    * 
    * Just Manhattan distance for now
    * */
    protected Double h(Utilities.MovePoint a, Utilities.MovePoint b) {
        return (Utilities.manhattan_distance(a,b));
    }

    protected  List<Utilities.MovePoint> generateSuccessors(Utilities.MovePoint node) {
        ArrayList<Utilities.MovePoint> res = new ArrayList<Utilities.MovePoint>();
        for (Card.ROBOT_MOVE move : Card.ROBOT_MOVE.values()) {
            res.add(Utilities.MovePath(this.map, node.getLocation(), new Card.ROBOT_MOVE[] {move})[0]);
        }     
        return res;
    }

    protected boolean isGoal(Utilities.MovePoint node) {
        return node.sameLocation(this.goal);
    }

    public Pathfinder(GameMap map, Info info) {
        super();
        this.map = map;
        this.info = info;
    }
    
    /* Prepare and compute a path of lowest total cost from a start to a goal location
    *  Total cost is defined as total risk, damage, and Manhattan distance incurred on the path
    *
    *  TODO - improve Manhattan distance to better account for card movement possibilities
    * */
    public int get_path(BoardLocation start, BoardLocation goal) {
        this.goal = new Utilities.MovePoint(goal);
        List<Utilities.MovePoint> path = compute(new Utilities.MovePoint(start));

        /*
        int cost = 0;
        for (Utilities.MovePoint p : path) {
            cost += p.getRisk() + p.getDamage();
        }
        return new PathResult(risk, null);
        */

        return (int)(double)this.getCost();
    }

    /*
    public static class PathResult {
        public int total_risk;
        public Card.ROBOT_MOVE next_card_type;
        public PathResult(int risk, Card.ROBOT_MOVE type) { total_risk = risk; next_card_type = type; }
    }
    */
    
}

